package com.xhcl.system.service.impl;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.StringUtil;
import org.apache.shiro.codec.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.xhcl.system.mapper.TSrhsJtmxMapper;
import com.xhcl.system.mapper.TSrhsPztiFzhsMapper;
import com.xhcl.system.mapper.TSrhsPztiMapper;
import com.xhcl.system.mapper.TSrhsPztoMapper;
import com.xhcl.system.domain.TSrhsJtmx;
import com.xhcl.system.domain.TSrhsPzti;
import com.xhcl.system.domain.TSrhsPztiFzhs;
import com.xhcl.system.domain.TSrhsPzto;
import com.xhcl.system.domain.TSrhsZyk;
import com.xhcl.system.service.ITSrhsHsxtcsService;
import com.xhcl.system.service.ITSrhsPztoService;
import com.xhcl.system.service.ITSrhsZykService;
import com.alibaba.fastjson.JSON;
import com.xhcl.common.core.text.Convert;
import com.xhcl.common.exception.BusinessException;
import com.xhcl.common.utils.DateUtils;

/**
 * 凭证头Service业务层处理
 * 
 * @author xhcl
 * @date 2020-09-02
 */
@Service
public class TSrhsPztoServiceImpl implements ITSrhsPztoService 
{
    @Autowired
    private TSrhsPztoMapper tSrhsPztoMapper;
    
    @Autowired
    private TSrhsPztiMapper tSrhsPztiMapper;
    
    @Autowired
    private TSrhsPztiFzhsMapper tSrhsPztiFzhsMapper;
    
    @Autowired
    private ITSrhsHsxtcsService tSrhsHsxtcsService;
    
    @Autowired
    private ITSrhsZykService iTSrhsZykService;

    /**
     * 查询凭证头
     * 
     * @param pztxh 凭证头ID
     * @return 凭证头
     */
    @Override
    public TSrhsPzto selectTSrhsPztoById(Long pztxh)
    {
        return tSrhsPztoMapper.selectTSrhsPztoById(pztxh);
    }

    /**
     * 查询凭证头列表
     * 
     * @param tSrhsPzto 凭证头
     * @return 凭证头
     */
    @Override
    public List<TSrhsPzto> selectTSrhsPztoList(TSrhsPzto tSrhsPzto)
    {
        return tSrhsPztoMapper.selectTSrhsPztoList(tSrhsPzto);
    }

    /**
     * 新增凭证头
     * 
     * @param tSrhsPzto 凭证头
     * @return 结果
     * @throws UnsupportedEncodingException 
     */
    @Override
    @Transactional
    public int insertTSrhsPzto(TSrhsPzto tSrhsPzto) throws BusinessException, UnsupportedEncodingException
    {
    	
    	if (tSrhsPzto==null ) {
    		throw new BusinessException("凭证信息为空！");
    	}
    	if (tSrhsPzto.getPzrq()==null ||tSrhsPzto.getPzrq().length()!=10) {
    		throw new BusinessException("会计日期为空！");
    	}
    	if (tSrhsPzto.getParams().get("pzti")==null) {
    		throw new BusinessException("凭证信息为空！");
    	}
    	List<TSrhsPzti> pztiList=JSON.parseArray(tSrhsPzto.getParams().get("pzti").toString(),TSrhsPzti.class);
    	if (CollectionUtils.isEmpty(pztiList)) {
    		throw new BusinessException("凭证信息为空！");
    	}
    	if (pztiList.size()<2) {
    		throw new BusinessException("凭证分录条数不正确！");
    	}
    	BigDecimal dfjes=new BigDecimal(0);
    	BigDecimal jfjes=new BigDecimal(0);
    	int i=1;
    	for (TSrhsPzti tSrhsPzti:pztiList) {
    		if (StringUtils.isEmpty(tSrhsPzti.getKmdm())){
    			throw new BusinessException("凭证分录"+i+"条科目为空！");
    		}
    		if (tSrhsPzti.getJfje()!=null && tSrhsPzti.getDfje()!=null 
    				&& tSrhsPzti.getJfje().compareTo(new BigDecimal(0))!=0 
    				&& tSrhsPzti.getDfje().compareTo(new BigDecimal(0))!=0){
    			throw new BusinessException("凭证分录"+i+"条科目借贷方金额只能有一个！");
    		}
    		if (tSrhsPzti.getJfje()!=null) {
    			jfjes=jfjes.add(tSrhsPzti.getJfje());
    		}
    		if (tSrhsPzti.getDfje()!=null) {
    			dfjes=dfjes.add(tSrhsPzti.getDfje());
    		}
    		String kmfzmx=tSrhsPzti.getFzmx();
        	if (StringUtils.isNotEmpty(kmfzmx)) {
        		List<TSrhsPztiFzhs> list=JSON.parseArray(kmfzmx, TSrhsPztiFzhs.class);
        		BigDecimal fzmxjes=new BigDecimal(0);
        		for(TSrhsPztiFzhs fzhs:list ) {
        			String dwbm=fzhs.getDwbm();
        			if (StringUtils.isEmpty(dwbm)){
            			throw new BusinessException("凭证分录"+i+"条科目辅助明细单位信息为空！");
            		}if (fzhs.getJe()==null){
            			throw new BusinessException("凭证分录"+i+"条科目辅助明细金额为空！");
            		}
            		fzmxjes=fzmxjes.add(fzhs.getJe());
        		}
        		if (tSrhsPzti.getJfje()!=null && tSrhsPzti.getJfje().compareTo(new BigDecimal(0))!=0  ) {
        			if (tSrhsPzti.getJfje().compareTo(fzmxjes)!=0) {
        	    		throw new BusinessException("凭证分录"+i+"条科目借方金额与辅助明细金额不一致！");
        	    	}
        		}
        		if (tSrhsPzti.getDfje()!=null && tSrhsPzti.getDfje().compareTo(new BigDecimal(0))!=0 ) {
        			if (tSrhsPzti.getDfje().compareTo(fzmxjes)!=0) {
        	    		throw new BusinessException("凭证分录"+i+"条科目贷方金额与辅助明细金额不一致！");
        	    	}
        		}
        	}
    		i++;
    	}
    	if (dfjes.compareTo(jfjes)!=0) {
    		throw new BusinessException("凭证借贷方金额不一致！");
    	}
		String pzrq=tSrhsPzto.getPzrq();
		String year=pzrq.substring(0, 4);
		String term=pzrq.substring(5, 7);
		String rq=pzrq.substring(8, 10);
		tSrhsPzto.setNd(Long.valueOf(year));
		tSrhsPzto.setYf(Long.valueOf(term));
		tSrhsPzto.setRq(Long.valueOf(rq));
		tSrhsPzto.setPzzt(1L);
		Long pztxh=null;
		int icount=0;
		if (tSrhsPzto.getPztxh()!=null) {
			pztxh=tSrhsPzto.getPztxh();
			icount=tSrhsPztoMapper.updateTSrhsPzto(tSrhsPzto);
			//先删除后插入
			tSrhsPztiMapper.deleteTSrhsPztiByPztxh(pztxh);
			tSrhsPztiFzhsMapper.deleteTSrhsPztiFzhsByPztxh(pztxh);
		}else {
			//新增;
	    	pztxh=tSrhsPztoMapper.selectTSrhsPztoPztxh();
	    	tSrhsPzto.setPztxh(pztxh);
	    	Long pzbh=tSrhsPztoMapper.selectTSrhsPztoPzbh(tSrhsPzto);
	    	tSrhsPzto.setPzbh(pzbh);
	        icount=tSrhsPztoMapper.insertTSrhsPzto(tSrhsPzto);
		}
        Long ixh=1L;
        for (TSrhsPzti tSrhsPzti:pztiList) {
        	tSrhsPzti.setPztxh(pztxh);
        	tSrhsPzti.setXh(ixh);
        	tSrhsPztiMapper.insertTSrhsPzti(tSrhsPzti);
        	String fzmx=tSrhsPzti.getFzmx();
        	if (StringUtils.isNotEmpty(fzmx)) {
        		List<TSrhsPztiFzhs> list=JSON.parseArray(fzmx, TSrhsPztiFzhs.class);
        	
        		for(TSrhsPztiFzhs mxitem:list ) {
        			TSrhsPztiFzhs tSrhsPztiFzhs=new TSrhsPztiFzhs();
        			tSrhsPztiFzhs.setPztxh(pztxh);
        			tSrhsPztiFzhs.setXh(ixh);
        			tSrhsPztiFzhs.setPzn(Long.valueOf(year));
        			tSrhsPztiFzhs.setPzy(Long.valueOf(term));
        			tSrhsPztiFzhs.setPzr(Long.valueOf(rq));
        			tSrhsPztiFzhs.setJe(mxitem.getJe());
        			tSrhsPztiFzhs.setDwbm(mxitem.getDwbm());
        			tSrhsPztiFzhs.setDwmc(mxitem.getDwmc());
        			tSrhsPztiFzhs.setPjh(mxitem.getPjh());
        			tSrhsPztiFzhs.setXmbm(mxitem.getXmbm());
        			tSrhsPztiFzhs.setXmmc(mxitem.getXmmc());
        			tSrhsPztiFzhs.setYskm(mxitem.getYskm());
        			tSrhsPztiFzhs.setYskmmc(mxitem.getYskmmc());
        			tSrhsPztiFzhsMapper.insertTSrhsPztiFzhs(tSrhsPztiFzhs);
        		}
        		
        	}

        	ixh++;
        }
        //去重复的摘要
        List<TSrhsPzti> anewList=new ArrayList<TSrhsPzti>();
        for (TSrhsPzti tSrhsPzti:pztiList) {
        	TSrhsPzti tPzti=new TSrhsPzti();
        	tPzti.setZy(tSrhsPzti.getZy());
        	anewList.add(tPzti);
        }	
        List<TSrhsPzti> bnewList=removeDuplicate(anewList);
        for (TSrhsPzti tSrhsPzti:bnewList) {
        	if (StringUtils.isNotEmpty(tSrhsPzti.getZy())){
        		TSrhsZyk tSrhsZyk=new TSrhsZyk();
        		tSrhsZyk.setZybm("0000");
        		tSrhsZyk.setZynr(tSrhsPzti.getZy());
        		List<TSrhsZyk> zylist=iTSrhsZykService.selectTSrhsZykList(tSrhsZyk);
        		if (zylist.size()==0){
        			iTSrhsZykService.insertTSrhsZyk(tSrhsZyk);
        		}
        	}
        }
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("pztxh", pztxh);
        tSrhsPztoMapper.callcreateJtmx(map);
        if (!(map.get("outrev")!=null && map.get("outrev").equals("ok"))) {
    		   throw new BusinessException(map.get("outrev").toString());
    	   }
        return icount;
    }
   
    public static List removeDuplicate(List list) {   
        HashSet h = new HashSet(list);   
        list.clear();   
        list.addAll(h);   
        return list;   
    }
    /**
     * 修改凭证头
     * 
     * @param tSrhsPzto 凭证头
     * @return 结果
     */
    @Override
    public int updateTSrhsPzto(TSrhsPzto tSrhsPzto)
    {
        return tSrhsPztoMapper.updateTSrhsPzto(tSrhsPzto);
    }

    /**
     * 删除凭证头对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteTSrhsPztoByIds(String ids)
    {  
    	String[] arr=Convert.toStrArray(ids);
    	for (int i=0;i<arr.length;i++) {
    		TSrhsPzto tSrhsPzto=tSrhsPztoMapper.selectTSrhsPztoById(Long.valueOf(arr[i]));
    		if (tSrhsPzto==null) {
    			throw new BusinessException("未找到对应的凭证信息");
    		}
    		if (tSrhsPzto.getPzlb()!=1L) {
    			throw new BusinessException("非手工凭证不能删除");
    		}
    	}
    	for (int i=0;i<arr.length;i++) {
    		Map<String,Object> map=new HashMap<String,Object>();
            map.put("pztxh", arr[i]);
        	tSrhsPztoMapper.calldelVoucher(map);
        	 if (!(map.get("outrev")!=null && map.get("outrev").equals("ok"))) {
      		   throw new BusinessException(map.get("outrev").toString());
      	   }
    	}
    	return 1;
    }

    /**
     * 删除凭证头信息
     * 
     * @param pztxh 凭证头ID
     * @return 结果
     */
    @Override
    public int deleteTSrhsPztoById(Long pztxh) throws BusinessException
    {   
    	
    	TSrhsPzto tSrhsPzto=tSrhsPztoMapper.selectTSrhsPztoById(pztxh);
		if (tSrhsPzto==null) {
			throw new BusinessException("未找到对应的凭证信息");
		}
		if (tSrhsPzto.getPzlb()!=1L) {
			throw new BusinessException("非手工凭证不能删除");
		}
    	Map<String,Object> map=new HashMap<String,Object>();
        map.put("pztxh", pztxh);
    	tSrhsPztoMapper.calldelVoucher(map);
    	 if (!(map.get("outrev")!=null && map.get("outrev").equals("ok"))) {
  		   throw new BusinessException(map.get("outrev").toString());
  	   }
       return 1;
    }
    
    
    public int accountVoucherByPztxh(Long pztxh,String sh) throws BusinessException
    {
    	Map<String,Object> map=new HashMap<String,Object>();
        map.put("pztxh", pztxh);
        map.put("sh", sh);
    	tSrhsPztoMapper.callaccountVoucher(map);
    	 if (!(map.get("outrev")!=null && map.get("outrev").equals("ok"))) {
  		   throw new BusinessException(map.get("outrev").toString());
  	   }
       return 1;
    }
    public int accountVoucherByPztxhs(String ids,String sh) throws BusinessException
    {   
    	String ifone=tSrhsHsxtcsService.getHsxtcsnr("ifone");
    	String[] ptzxhs= Convert.toStrArray(ids);
    	for (int i=0;i<ptzxhs.length;i++) {
    		TSrhsPzto tSrhsPzto=tSrhsPztoMapper.selectTSrhsPztoById(Long.valueOf(ptzxhs[i]));
    		if (tSrhsPzto==null) {
    			throw new BusinessException("未找到对应的凭证信息");
    		}
    		 if (tSrhsPzto.getPzzt().equals(3L)) {
    			 throw new BusinessException("存在已记账的凭证");
    		 }
    		 if ((ifone != null) && (ifone.equals("0")) && (tSrhsPzto.getZd().equals(sh))) {
    			 throw new BusinessException("制单与审核不能是同一人");
    		 }
    	}
    	for (int i=0;i<ptzxhs.length;i++) {
    		Map<String,Object> map=new HashMap<String,Object>();
            map.put("pztxh", Long.valueOf(ptzxhs[i]));
            map.put("sh", sh);
        	tSrhsPztoMapper.callaccountVoucher(map);
        	 if (!(map.get("outrev")!=null && map.get("outrev").equals("ok"))) {
      		   throw new BusinessException(map.get("outrev").toString());
      	   }
    	}
        return 1;
    }
    
    public int unaccountVoucherByPztxh(Long pztxh,String sh) throws BusinessException
    {   
    	
    	TSrhsPzto tSrhsPzto=tSrhsPztoMapper.selectTSrhsPztoById(pztxh);
		if (tSrhsPzto==null) {
			throw new BusinessException("未找到对应的凭证信息");
		}
    	Map<String,Object> map=new HashMap<String,Object>();
        map.put("pzlx", 0);
        map.put("pzbh", tSrhsPzto.getPzbh());
    	tSrhsPztoMapper.callunaccountVoucher(map);
    	 if (!(map.get("outrev")!=null && map.get("outrev").equals("ok"))) {
  		   throw new BusinessException(map.get("outrev").toString());
  	   }
       return 1;
    }
    public int unaccountVoucherByPztxhs(String ids,String sh) throws BusinessException
    {   
    	String[] ptzxhs= Convert.toStrArray(ids);
    	for (int i=0;i<ptzxhs.length;i++) {
    		TSrhsPzto tSrhsPzto=tSrhsPztoMapper.selectTSrhsPztoById(Long.valueOf(ptzxhs[i]));
    		if (tSrhsPzto==null) {
    			throw new BusinessException("未找到对应的凭证信息");
    		}
    		 if (!tSrhsPzto.getPzzt().equals(3L)) {
    			 throw new BusinessException("存在未记账的凭证，不能反记账");
    		 }
    	}
    	for (int i=0;i<ptzxhs.length;i++) {
    		TSrhsPzto tSrhsPzto=tSrhsPztoMapper.selectTSrhsPztoById(Long.valueOf(ptzxhs[i]));
    		Map<String,Object> map=new HashMap<String,Object>();
            map.put("pzlx", 0);
            map.put("pzbh", tSrhsPzto.getPzbh());
        	tSrhsPztoMapper.callunaccountVoucher(map);
        	 if (!(map.get("outrev")!=null && map.get("outrev").equals("ok"))) {
      		   throw new BusinessException(map.get("outrev").toString());
      	   }
    	}
        return 1;
    }
    public List<TSrhsPzto> selectTSrhsPztiforKmmcList(TSrhsPzto tSrhsPzto){
    	List<TSrhsPzto> pztolist=tSrhsPztoMapper.selectTSrhsPztoList(tSrhsPzto);
    	List<TSrhsPzti> pztilist=tSrhsPztiMapper.selectTSrhsPztiforKmmcList(tSrhsPzto);
    	for (TSrhsPzto pzto:pztolist) {
    		List<TSrhsPzti> mxlist=pztilist.stream().filter(m->m.getPztxh().equals(pzto.getPztxh())).collect(Collectors.<TSrhsPzti>toList());
    		pzto.setSrhsPzti(mxlist);
    		pzto.setDwmc(tSrhsHsxtcsService.getHsxtcsnr("bjczmc"));
    	}
    	return pztolist;
    }
    
    
    public String doBreakCheck(Long year, Long month) throws BusinessException
    {
      List list = getBreakVoucherNums(year, month);
      if (list.size()==0) {
    	  return "0";
      }
      StringBuffer sb = new StringBuffer();
      if (list.size() > 0) {
        for (int i = 0; i < list.size(); i++) {
          if (((Integer)list.get(i)).intValue() > 0)
            sb.append("凭证" + list.get(i).toString() + "断号!\n");
          else
            sb.append("凭证" + -((Integer)list.get(i)).intValue() + 
              "重号!\n");
        }
      }
      throw new BusinessException(sb.toString());
    }

    private List getBreakVoucherNums(Long year, Long month) {
      
       TSrhsPzto tSrhsPzto=new TSrhsPzto();
       tSrhsPzto.setNd(year);
       tSrhsPzto.setYf(month);;
       List<TSrhsPzto> list = tSrhsPztoMapper.selectTSrhsPztoList(tSrhsPzto); 
       List breakNumsList = new ArrayList();
       int i = 1; 
       for (int j = 0; j < list.size(); j++) {
        int voucherNum = ((TSrhsPzto)list.get(j)).getPzbh().intValue();
        if (voucherNum < i) {
          breakNumsList.add(new Integer(-voucherNum));
          i--;
        } else {
          while (voucherNum > i) {
            breakNumsList.add(new Integer(i));
            i++;
          }
        }
        i++;
      }
      return breakNumsList;
    }
    @Transactional
    public String modifyDate(String pzrq, Long pztxh) throws BusinessException
    {
        TSrhsPzto o=tSrhsPztoMapper.selectTSrhsPztoById(pztxh); 
        if (o.getPzzt().intValue() == 3) {
            return "凭证已记账";
        }
        Date newDate =  DateUtils.parseDate(pzrq);
        Date hsqj =  DateUtils.parseDate(tSrhsHsxtcsService.getHsxtcsnr("year") + "-" +tSrhsHsxtcsService.getHsxtcsnr("term") + "-01");
        if (newDate.after(new Date())) {
            return "调整日期请勿超当前日期";
        }
        if (newDate.before(hsqj)) { 
            return "调整日期请在当前核算期间或其之后";
        } 
      TSrhsPzto newPzto=new TSrhsPzto();
      newPzto.setNd(Long.valueOf(pzrq.substring(0,4)));
      newPzto.setYf(Long.valueOf(pzrq.substring(5,7)));
      newPzto.setRq(Long.valueOf(pzrq.substring(8,10)));
      Long pzbh=tSrhsPztoMapper.selectTSrhsPztoPzbh(newPzto);
      newPzto.setPztxh(pztxh);
      newPzto.setPzbh(pzbh);
      tSrhsPztoMapper.updateTSrhsPzto(newPzto);
     
      Map<String,Object> pmap=new HashMap<String,Object>();
      pmap.put("pzrq", pzrq);
      pmap.put("pzbh", pzbh);
      pmap.put("pztxh", pztxh);
      tSrhsPztoMapper.updatetsrhsjtmxpzrq(pmap);
      tSrhsPztoMapper.updatetsrhsrfspzrq(pmap);
      return "ok";
    }
}
